
/* GCSx
** WORLDEDIT.H
**
** World storage- editor-only functionality
*/

/*****************************************************************************
** Copyright (C) 2003-2006 Janson
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
*****************************************************************************/

#ifndef __GCSx_WORLDEDIT_H_
#define __GCSx_WORLDEDIT_H_

class WorldEdit : public World, virtual public SaveLoad {
public:
    typedef std::map<int, class LayerEdit*> LayerIndex;
    typedef std::map<int, class SpawnEdit*> SpawnIndex;
    typedef std::map<int, class FolderEdit*> FolderIndex;
    
private:
    // Our file, in writable format; should be same as file member
    class WorldFile* saveFile;
    int headerModified;
    int contentModified;

    // Resources, indexed by id, that only need to be searched for in editor
    LayerIndex layersById;
    SpawnIndex spawnsById;
    FolderIndex foldersById;
    
    // Points to our node on the world browser, we must keep it updated
    // as we add and remove scenes, etc.
    class TreeView* browserNode;
    
    // List of all currently open worlds
    static std::set<class WorldEdit*>* allWorlds;
    
    // Treeview handling constants
    enum {
        TREEVIEW_WORLD = 1,
        TREEVIEW_SCENE,
        TREEVIEW_TILESET,
        TREEVIEW_FONT,
        TREEVIEW_NOTES,
        TREEVIEW_ANIMGROUP,
        TREEVIEW_SCRIPT,
        TREEVIEW_FOLDER,
    };

public:
    WorldEdit() throw_File; // Default constructor creates a blank new "Untitled" world
    WorldEdit(const char* wFilename) throw_File; // Opens an existing world for editing
    virtual ~WorldEdit(); // Closes/deletes all resources, removes all from browser

    // Change properties; handles undo
    void setTitle(const std::string& newTitle, Window* srcWin = NULL, Window* exWin = NULL) throw_Undo;
    // (doesn't check ID for accuracy)
    void setStartScene(int sId, Window* srcWin = NULL, Window* exWin = NULL) throw_Undo;

    // Returns true if OK pressed
    int propertiesDialog(Window* srcWin = NULL, Window* exWin = NULL);

    // Add and remove from byId indices
    // Safe to change name, as not indexed by name
    // Only call these when adding/removing layers/spawns
    // Indexing scenes automatically gets layers/spawns too now
    void indexLayer(LayerEdit* addLayer);
    void deindexLayer(LayerEdit* remLayer);
    void indexSpawn(SpawnEdit* addSpwan);
    void deindexSpawn(SpawnEdit* remSpawn);
    void indexScene(Scene* addScene);
    void deindexScene(Scene* remScene);
    void indexFolder(FolderEdit* addFolder);
    void deindexFolder(FolderEdit* remFolder);

    // Find items based on name or iterate sequence
    // Designed for runtime efficiency
    class LayerEdit* findLayer(int fId) const;
    LayerIndex::const_iterator beginLayer() const { return layersById.begin(); }
    LayerIndex::const_iterator endLayer() const { return layersById.end(); }
    
    class SpawnEdit* findSpawn(int fId) const;
    SpawnIndex::const_iterator beginSpawn() const { return spawnsById.begin(); }
    SpawnIndex::const_iterator endSpawn() const { return spawnsById.end(); }
    
    class FolderEdit* findFolder(int fId) const;
    FolderIndex::const_iterator beginFolder() const { return foldersById.begin(); }
    FolderIndex::const_iterator endFolder() const { return foldersById.end(); }

    // Find items based on block type- currently used by folders (and undo, for folders)
    SaveLoad* findItem(int blockType, int id);

    // Create new IDs    
    int unusedSceneId() const;
    int unusedTileSetId() const;
    int unusedAnimGroupId() const;
    int unusedScriptId() const;
    int unusedLayerId() const;
    int unusedSpawnId() const;
    int unusedFolderId() const;

    // Our undo handler
    UndoBuffer undo;

    // File operations
    // Returns true if was saved
    int save(); // Calls saveAs if no filename ever assigned
    int saveAs();
    
    // Close; asks to save if modified; then deletes self if appropriate
    // Returns true if was closed and deleted; justSave causes us to
    // check modified status and save as if closing, but don't actually
    // close yet; returns true if ok, false if cancelled; dontAsk tells
    // us not to ask about being modified
    int close(int justSave = 0, int dontAsk = 0);

    // Delete a resource- removes from our list AND actually deletes it
    // Returns 1 if deleted; 0 if couldn't be deleted (such as user cancelled)
    int deleteTileset(class TileSetEdit* toDelete, Window* srcWin = NULL);
    int deleteScene(class SceneEdit* toDelete, Window* srcWin = NULL);
    int deleteAnimGroup(class AnimGroupEdit* toDelete, Window* srcWin = NULL);
    int deleteScript(class ScriptEdit* toDelete, Window* srcWin = NULL);
    int deleteFolder(class FolderEdit* toDelete, Window* srcWin = NULL);
    
    // Readds a resource that was deleted and disassociated earlier
    void readdTileset(class TileSetEdit* toAdd);
    void readdScene(class SceneEdit* toAdd);
    void readdAnimGroup(class AnimGroupEdit* toAdd);
    void readdScript(class ScriptEdit* toAdd);
    void readdFolder(class FolderEdit* toAdd);

    // Adds an outside-created resource (as a single undo create event, also)
    void importTileSet(class TileSetEdit* toAdd, int openWindow = 1, Window* srcWin = NULL);
    void importScene(class SceneEdit* toAdd, int openWindow = 1, Window* srcWin = NULL);

    // Tells world to add itself to the world browser
    void addToBrowser(class TreeView* worldBrowser);
    
    // Other editor windows cascade to these
    Window::CommandSupport supportsCommand(int code) const;
    int commandEvent(int code);
    
    // Treeview event handling
    int treeviewEvent(int code, int command, int check);
    static int treeviewEventWrap(void* ptr, int code, int command, int check);
    
    // Asks to save all modified worlds; returns true if everything ok, false 
    // if any hit cancel; intended for use when quitting
    static int modifiedAll();
    // Closes or saves all currently open worlds
    static void closeAll(int dontAsk = 0);
    static void saveAll();
    
    // File access
    int isHeaderModified() const;
    int isContentModified() const;
    // (overrides World, we actually load notes)
    void loadContent(class FileRead* file);
    Uint32 saveHeader(class FileWrite* file) throw_File;
    void saveContent(class FileWrite* file);
    void saveSuccess();
    void cachedContent(class FileRead* file, int oldData);
    void setHeaderModified();
    void setGlobalLinksModified();
    
    // Verifies if a given world is still open
    static int verifyWorld(class WorldEdit* verify);
    // Returns number of worlds open
    static int countWorlds();
    // Returns currently open worlds, in order (0 is first position; returns NULL if done)
    static class WorldEdit* listWorlds(int pos);
};

#endif

